﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of IonexFileReader.                                       **
**                                                                              **
**  IonexFileReader is free software: you can redistribute it and/or modify     **
**  it under the terms of the GNU General Public License as published by        **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  IonexFileReader is distributed in the hope that it will be useful,          **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU General Public License for more details.                                **
**                                                                              **
**  You should have received a copy of the GNU General Public License           **
**  along with IonexFileReader. If not, see <https://www.gnu.org/licenses/>.    **
**********************************************************************************/
#include "IonexFile.h"
#include "Private/IonexPaser.h"

#include <tao/pegtl.hpp>

namespace Ionex
{
struct IonexFile::Impl
{
    std::string source;
    IonexPaser parser;
    inline Impl(const std::string& s) : source(s) {}
    inline Impl(std::string&& s) : source(std::move(s)) {}
};

IonexFile::IonexFile(const std::string& source) : m_impl(std::make_unique<Impl>(source)) {}

IonexFile::IonexFile(std::string&& source) : m_impl(std::make_unique<Impl>(std::move(source))) {}

IonexFile::~IonexFile() {}

bool IonexFile::load()
{
    if (m_impl->source.empty())
        return false;
    if (tao::pegtl::parse<PEG::Rule, PEG::Action>(tao::pegtl::string_input(m_impl->source, ""), m_impl->parser))
    {
        return true;
    }
    return false;
}

double IonexFile::fileVersion() const { return m_impl->parser.version; }

const std::string& IonexFile::fileType() const { return m_impl->parser.fileType; }

SatelliteSystem IonexFile::satelliteSystem() const { return m_impl->parser.system; }

const std::string& IonexFile::createByProgram() const { return m_impl->parser.program; }

const std::string& IonexFile::createByAgency() const { return m_impl->parser.agency; }

const std::string& IonexFile::createDateTime() const { return m_impl->parser.createDateTime; }

const std::vector<std::string>& IonexFile::descriptions() const { return m_impl->parser.descriptions; }

const std::vector<std::string>& IonexFile::comments() const { return m_impl->parser.comments; }

const DateTime& IonexFile::epochOfFirstMap() const { return m_impl->parser.epochOfFirstMap; }

const DateTime& IonexFile::epochOfLastMap() const { return m_impl->parser.epochOfLastMap; }

int IonexFile::interval() const { return m_impl->parser.interval; }

int IonexFile::ofMapsInFile() const { return m_impl->parser.ofMapsInFile; }

MapingFunction IonexFile::mapingFunction() const { return m_impl->parser.mapingFunction; }

double IonexFile::elevationCutOff() const { return m_impl->parser.elevationCutOff; }

double IonexFile::baseRadius() const { return m_impl->parser.baseRadius; }

int IonexFile::mapDimension() const { return m_impl->parser.mapDimension; }

std::tuple<double, double, double> IonexFile::hgt1Hgt2DHgt() const
{
    const auto& p = m_impl->parser;
    return { p.hgt1, p.hgt2, p.dhgt };
}

std::tuple<double, double, double> IonexFile::lat1Lat2DLat() const
{
    const auto& p = m_impl->parser;
    return { p.lat1, p.lat2, p.dlat };
}

std::tuple<double, double, double> IonexFile::lon1Lon2DLon() const
{
    const auto& p = m_impl->parser;
    return { p.lon1, p.lon2, p.dlon };
}

const std::optional<int>& IonexFile::exponent() const { return m_impl->parser.exponent; }

const std::vector<DataMap>& IonexFile::tecMaps() const { return m_impl->parser.tecMaps; }

const std::vector<DataMap>& IonexFile::rmsMaps() const { return m_impl->parser.rmsMaps; }

const std::vector<DataMap>& IonexFile::heightMaps() const { return m_impl->parser.heightMaps; }

} // namespace Ionex